#ifndef SimComm_H
#define SimComm_H

#include <QStringList>
#include <QTcpServer>
#include <qmap.h>
#include <qglobal.h>
#include <qdom.h>


extern quint32 setBitsVal(const quint32 dst, const unsigned char start, 
      const unsigned char end, quint32 val);


#pragma pack(1)
 typedef struct _IOIN_DATA
{
    quint32 DataId;
    quint32 dataSz;
    char IoInData[4];
    char IoInErr[4];
    char IoOutErr[4];
    char IoInChn;
    char IoOutChn;
    quint16 IoBoardErr;
}IOIN_DATA;

 typedef struct _spd
 {
     unsigned char VelocityStatus[2];
     quint32 VelocityCount[4];
     quint32 VelocityFrequency[4];
     unsigned char AccelerationStatus[2];
     qint16 AccelerationValue[2];
     unsigned char DopperStatus;
     quint16 DopperVelocity;
     quint16 DopperDisatanceChg1;
     quint16 DopperDisatanceChg2;
     quint32 BeconID;
     unsigned char BeconValidStatus;
     unsigned char BeconData[128];
     quint32 BeconVelocityCount[4];
     unsigned char TicStatus;

     struct _spd()
     {
        for (int i = 0; i< 2; i++)
        {
            AccelerationStatus[i] = 0x55;
            VelocityStatus[i] = 0x55;
        }
        TicStatus = 0x55;

        DopperStatus = 0;
        DopperStatus = setBitsVal(DopperStatus,6,7,2);
        DopperStatus = setBitsVal(DopperStatus,3,5,6);
        DopperStatus = setBitsVal(DopperStatus,1,1,1);
        DopperStatus = setBitsVal(DopperStatus,0,0,1);
     }

 }SPD;

 typedef struct _ROResultTrain
 {
    QString ID;
    QString HeaderTkId;
    QString TailerTkId;
    QString TkId;
    QString HeaderOffset;
    QString TailerOffset;
    QString Milepost;
    QString TSList;
    QString SPEED;
    QString RSDirection;
 }ROResultTrain;

typedef struct _stCCData
{
     //rollstock class xml format, according c# code version
    QByteArray RVin;

    ////Data struct
//|4 Bytes	|12 Bytes    |	12 Bytes	|12 Bytes   | 	12 Bytes  |
//|Electirc | IO board 1 | IO board 2   |IO board 3	|IO board 4   |
    QByteArray IOin;
    QByteArray IOinLastTime;

   // QByteArray arryROResult2CC;
    SPD        ROResultSpeedData;

////Data struct
//|IOIN_DATA | IOIN_DATA | IOIN_DATA   |IOIN_DATA	|SPEED   |
   // QHash<int, QByteArray> hashROResult2CC;
     QByteArray ROResultIO;

//    <root>
//  <Train>
//     <ID> </ID>
//     <HeaderTkId> </HeaderTkId>
//     <TailerTkId> </TailerTkId>
//     <TkId> </TkId>
//     <HeaderOffset> </HeaderOffset>
//     <TailerOffset> </TailerOffset>
//     <Milepost> </Milepost>
//     <TSList> </TSList>
//     <SPEED> </SPEED>
//     <RSDirection> </RSDirection>
//  </Train>
//....
//</Train>
    QByteArray ROResultTrainData;

}stCCData;

typedef struct _stFOData
{
     //SIM_REG_STAT
//<Root>
//  <Switchs>
//    <W0101>0</W0101>
//    <W0103>0</W0103>
//    </Switchs>
//  <Signals>
//    <D1>RED</D1>
//    <SJ1>RED</SJ1>
//    <S0101>RED</S0101>
//    <S0105>RED</S0105>
//     </Signals>
//  <Tracks>
//    <DT1>0</DT1>
//    <ZHG1>0</ZHG1>
//     </Tracks>
//</Root>
    QByteArray arryFOStatein;
    QByteArray arryFOTrnin;
}stFOData;

typedef struct _stFVData
{
    //<root>
//<ChangeItem>
//		<name>XXX</name>
//		<Status>XXX</Status>
//		<Value>XXX</Value>
//</ChangeItem>
//</root>
    QByteArray controlCommandIn;
}stFVData;

typedef struct _stRVData
{
    QByteArray data;
}stRVData;

class SimComm : public QTcpServer
{
    Q_OBJECT

public:
    SimComm(QObject *parent = 0);
    ~SimComm();

protected:
   void incomingConnection(int socketDescriptor);

private slots:

    //void processReadyRead();
    void simCCCome(const QByteArray& byte, const int id, QTcpSocket* sock );
    void simRVCome(const QByteArray& byte, const int id, QTcpSocket* sock);
    void simFOStatCome(const QByteArray& byte, const int id, QTcpSocket* sock );
    void simFOTrnCome(const QByteArray& byte, const int id, QTcpSocket* sock);
    void simFVCome(const QByteArray& byte, const int id, QTcpSocket* sock);
    
    void timeout();

private:
    
    void startROModle(int id);
    QByteArray RORestult2Str(const ROResultTrain& train);

    void send2CC(const int id);

    void simCCComePre(const int id, QTcpSocket* sock);
    void simRVComePre(const int id, QTcpSocket* sock);
    void simFVComePre(const int id, QTcpSocket* sock);
    void simFOComePre(const int id, QTcpSocket* sock);
    
   
private:

    typedef struct _peerInfo
    {
        QString type; //now is unused.
        int fd;
        int id; //from env when ZC/CC startup 
        QTcpSocket* connection;
    }peerInfo;

    enum runMode
    {
        NONE = 1,
        ATO,
        ATP,
        CC,//ATO and ATP
        ZC
    };

private:
    QHash<int, peerInfo> hashRawPeerInfo;
    

    QHash<int, peerInfo> hashPeerInfoCC;
    QHash<int, peerInfo> hashPeerInfoRV;
    QHash<int, peerInfo> hashPeerInfoFV;
    QHash<int, peerInfo> hashPeerInfoFO;
   
    runMode   m_runmode;

    //include RO result
    QHash<int,stCCData> hashCCData; //id map to ccData, id is 1,2,3 that is cc SimSpServer
    QHash<int,stRVData> hashRVData;
    stFOData FOData;
    stFVData FVData;
    
};

#pragma pack()
#endif
